package com.tengju.motivation.domain.model.activity;

import com.tengju.motivation.domain.model.goods.Goods;
import com.tengju.motivation.domain.model.goods.GoodsType;
import com.tengju.motivation.domain.shared.Entity;
import com.tengju.motivation.domain.shared.ValueObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Value;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 活动信息
 */

@Value
public class Activity implements Entity<Activity> {

    public static final ActivityTargetGrowType LIMIT_GROW_TYPE = ActivityTargetGrowType.GIFT_PACK;

    /**
     * 活动ID
     */
    ActivityId activityId;
    /**
     * 活动名称
     */
    String name;

    /**
     * 活动开始时间
     */
    LocalDateTime startTime;

    /**
     * 活动结束时间
     */
    LocalDateTime endTime;

    /**
     * 活动创建时间
     */
    LocalDateTime createTime;

    /**
     * 活动额外信息
     */
    ActivityExtraInfo extraInfo;

    @Override
    public boolean sameIdentityAs(Activity other) {
        return other != null && this.getActivityId().sameValueAs(other.getActivityId());
    }


    public Activity(ActivityId activityId, String name, LocalDateTime startTime,
                    LocalDateTime endTime, LocalDateTime createTime, ActivityExtraInfo activityExtraInfo) {
        this.activityId = activityId;
        this.name = name;
        this.startTime = startTime;
        this.endTime = endTime;
        this.createTime = createTime;
        this.extraInfo = activityExtraInfo;
    }


    public boolean isSale() {
        return extraInfo.getActivityType() == ActivityType.SALE;
    }

    /**
     * 校验活动是否进行中
     */
    public boolean isInProgress() {
        LocalDateTime now = LocalDateTime.now();
        return now.isAfter(startTime) && now.isBefore(endTime);
    }

    /**
     * 校验活动是否有效
     *
     * @return 是否有效
     */
    public boolean isValid() {
        return checkValid() == null;
    }

    /**
     * 校验活动是否有效
     *
     * @return 不合法原因
     */
    public String checkValid() {
        //人群只能为VTN
        if (ActivityUserType.VTN != extraInfo.getUserType()) {
            return "人群必须为VTN";
        }

        if (extraInfo.getIntentionCrowdId() == null) {
            return "意向人群不能为空";
        }

        ActivityType activityType = extraInfo.getActivityType();
        if (ActivityType.SALE == activityType) {// 销售活动
            //目标为出货额
            if (extraInfo.getTargetSaleType() != ActivityTargetSaleType.MONEY_OUT) {
                return "目标必须为出货额";
            }
            GoodsType limitGoodsType = Optional.ofNullable(extraInfo.getLimitGoods())
                    .map(ActivityExtraInfo.LimitGoods::getLimitGoodsType).orElse(null);
            //指定不参与仅支持品牌
            if ((extraInfo.getLimitGoods().getLimitSolution() == LimitSolution.EXCLUDE
                    && limitGoodsType != GoodsType.BRAND)) {
                return "指定不参与仅支持品牌";
            }
            //支持品牌、商品，暂不支持货品
            if (extraInfo.getLimitGoods().getLimitSolution() == LimitSolution.NONE
                    || GoodsType.BRAND == limitGoodsType || GoodsType.SPU == limitGoodsType) {
                return null;
            } else {
                return "支持品牌、商品，暂不支持货品";
            }
        }
        //招募活动
        else if (ActivityType.GROWTH == activityType) {
            if (extraInfo.getTargetGrownUserLevel() == null) {
                return "招募活动受众人群不能为空";
            }
            if (extraInfo.getTargetGrowTypes() != null && extraInfo.getTargetGrowTypes().size() == 1
                    && extraInfo.getTargetGrowTypes().contains(LIMIT_GROW_TYPE)) {
                return null;
            } else {
                return "招募活动仅支持礼包招募";
            }
        } else {
            return "仅支持销售和招募活动";
        }
    }

    /**
     * 活动持续天数
     */
    public long lastDuration() {
        return ChronoUnit.DAYS.between(startTime.toLocalDate(), endTime.minusSeconds(1).toLocalDate()) + 1;
    }


    @Data
    @AllArgsConstructor
    public static class ActivityExtraInfo implements ValueObject<ActivityExtraInfo> {

        /**
         * 活动类型
         */
        private ActivityType activityType;
        /**
         * 活动会员类型
         * 销售活动时仅支持VTN
         * 招募活动支持VTN和ABM
         */
        private ActivityUserType userType;

        /**
         * 活动目标类型
         */
        private ActivityTargetType targetType;

        /**
         * 活动销售目标类型
         */
        private ActivityTargetSaleType targetSaleType;
        /**
         * 增长活动目标等级
         */
        private UserLevel targetGrownUserLevel;

        /**
         * 活动限制人群范围
         */
        private List<UserLevel> limitCustomerLevel;

        /**
         * 活动意向人群ID
         */
        private CrowdId intentionCrowdId;

        /**
         * 活动限制商品范围
         */
        private LimitGoods limitGoods;


        /**
         * 招募活动升级方式
         */
        private Set<ActivityTargetGrowType> targetGrowTypes;

        /**
         * 活动预热时间
         */
        private LocalDateTime warmStartTime;

        /**
         * 活动冻结时间
         */
        private LocalDateTime freezeStartTime;


        public List<String> getLimitCustomerLevelNames() {
            return Optional.ofNullable(limitCustomerLevel)
                    .map(list -> list.stream()
                            .map(UserLevel::getDesc)
                            .collect(Collectors.toList())
                    )
                    .orElse(new ArrayList<>());
        }

        @Data
        @AllArgsConstructor
        public static class LimitGoods {

            GoodsType limitGoodsType;

            LimitSolution limitSolution;

            List<Goods> goodsList;

        }

        @Override
        public boolean sameValueAs(ActivityExtraInfo that) {
            return activityType == that.activityType
                    && userType == that.userType
                    && targetType == that.targetType
                    && Objects.equals(warmStartTime, that.warmStartTime)
                    && Objects.equals(freezeStartTime, that.freezeStartTime);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            return this.sameValueAs((ActivityExtraInfo) o);
        }

        @Override
        public int hashCode() {
            return Objects.hash(activityType, userType, targetType, warmStartTime, freezeStartTime);
        }
    }


}
